// Copyright (C) 2012 Volkov Zachar
// This file is part of the "zAxis Game Engine".
// For conditions of distribution and use, see copyright notice zx_Common.hpp

#include "zx_Video.hpp"
#include "gl/glew.h"

namespace zx {

//----------------------------------------------------------------------------//
//----------------------------------------------------------------------------//
VertexBuffer::VertexBuffer( uint _size, const void* _data, BufferUsage _usage ) : m_size( _size ), m_handle( 0 )
{
     glGenBuffers( 1, &m_handle );
     glBindBuffer( GL_ARRAY_BUFFER, m_handle );
     if( _size )
     {
          glBufferData( GL_ARRAY_BUFFER, _size * sizeof( Vertex ), _data, VideoDriver::_glBufferUsage( _usage ) );
     }
     //glBindBuffer( GL_ARRAY_BUFFER, 0 );
}
//----------------------------------------------------------------------------//
VertexBuffer::~VertexBuffer( void )
{
     glDeleteBuffers( 1, &m_handle );
}
//----------------------------------------------------------------------------//
void VertexBuffer::_Bind( void )
{
     GLint _current_buffer = 0;
     glGetIntegerv( GL_ARRAY_BUFFER_BINDING, &_current_buffer );

     if( _current_buffer != m_handle )
     {
          glBindBuffer( GL_ARRAY_BUFFER, m_handle );
     }
}
//----------------------------------------------------------------------------//
void VertexBuffer::_Unbind( void )
{
     GLint _current_buffer = 0;
     glGetIntegerv( GL_ARRAY_BUFFER_BINDING, &_current_buffer );

     if( _current_buffer == m_handle )
     {
          glBindBuffer( GL_ARRAY_BUFFER, m_handle );
     }
}
//----------------------------------------------------------------------------//
void VertexBuffer::Read( void* _dst, uint _offset, uint _count )
{
     _Bind();
     glGetBufferSubData( GL_ARRAY_BUFFER, _offset * sizeof( Vertex ), _count * sizeof( Vertex ), _dst );
     //_Unbind();
}
//----------------------------------------------------------------------------//
void VertexBuffer::Write( const void* _src, uint _offset, uint _count )
{
     _Bind();
     glBufferSubData( GL_ARRAY_BUFFER, _offset * sizeof( Vertex ), _count * sizeof( Vertex ), _src );
     //_Unbind();
}
//----------------------------------------------------------------------------//
Vertex* VertexBuffer::Discard( uint _new_size, BufferUsage _usage )
{
     _Bind();
     glBufferData( GL_ARRAY_BUFFER, (m_size = _new_size) * sizeof( Vertex ), 0, VideoDriver::_glBufferUsage( _usage ) );
     void* _data = glMapBuffer( GL_ARRAY_BUFFER, GL_READ_WRITE );
     //_Unbind();
     return reinterpret_cast< Vertex* >( _data );
}
//----------------------------------------------------------------------------//
Vertex* VertexBuffer::Lock( AccessMode _access )
{
     _Bind();
     void* _data = glMapBuffer( GL_ARRAY_BUFFER, VideoDriver::_glAccessMode( _access ) );
     //_Unbind();
     return reinterpret_cast< Vertex* >( _data );
}
//----------------------------------------------------------------------------//
void VertexBuffer::Unlock( void )
{
     _Bind();
     glUnmapBuffer( GL_ARRAY_BUFFER );
     //_Unbind();
}
//----------------------------------------------------------------------------//
//----------------------------------------------------------------------------//

} // namespace zx
